# This code is so you can run the samples without installing the package
import sys
import os
sys.path.insert(0, os.path.join(os.path.dirname(__file__), '../..'))

# stdlib

#pyglet
from pyglet.gl import *

# cocos2d related
from cocos.layer import Layer, ColorLayer
from cocos.scene import Scene
from cocos.director import director
from cocos.actions import *
from cocos.sprite import *
from cocos.menu import *
from cocos.text import *
from cocos.euclid import *
from monster import Character, Tatu, Monster
from random import randint
from pathfinding import AStar
import HUD

import threading

__all__ = ['get_newgame']

class Level(Layer):
    is_event_handler = True
    def __init__(self):
        super( Level, self ).__init__()

        #background
        self.add(HUD.BackgroundLayer(), z=-1)
        self.events = []
        self.garchers = []
        #bitmap mask and a* structure for pathfinding
        
        collition_layer = HUD.CollitionLayer()
        self.add(collition_layer, z=10)
        collition_bitmap_mask = collition_layer.bitmap_mask

        self.astar = AStar(collition_bitmap_mask)
        
        #level title
        label = Label('level 1', font_name='Edit Undo Line BRK',
                        font_size=30,
                        anchor_y='center',
                        anchor_x='center',
                        color=(204,164,164,255) )
        label.position = (400, 550)

        self.selected = None
        self.tatues = []

        self.character = Character('monster.png')
        self.character.setup_animation(1, 1)
        self.character.set_pos(200, 200)
        self.posx = 100
        self.posy = 240
        self.add(self.character.sprite)
        self.add(label)
        self.schedule(self.all_time)
        self.males = []
        self.females = []
        self.male_tatu = Tatu('Tatu_Male.png', gender = 'male')
        self.males.append(self.male_tatu)
        self.male_tatu.setup_animation(12, 1)
        self.male_tatu.set_pos(200, 300)
        self.female_tatu = Tatu('Tatu_Female.png', gender = 'female')
        self.females.append(self.female_tatu)
        self.female_tatu.setup_animation(12, 1)
        self.female_tatu.set_pos(400, 300)
        
        self.monsters = []

        self.add(self.male_tatu.sprite)
        self.add(self.female_tatu.sprite)

        self.tatues.append(self.female_tatu)
        self.tatues.append(self.male_tatu)

        self.schedule_interval( self.monster_factory, 4 )

        self.number_of_monsters = 0

    def on_mouse_press (self, x, y, buttons, modifiers):
        """This function is called when any mouse button is pressed

        (x, y) are the physical coordinates of the mouse
        'buttons' is a bitwise or of pyglet.window.mouse constants LEFT, MIDDLE, RIGHT
        'modifiers' is a bitwise or of pyglet.window.key modifier constants
            (values like 'SHIFT', 'OPTION', 'ALT')
        """
        for tatu in self.tatues:
            if tatu.sprite.contains(x, y):
                self.selected = tatu
                break
        if self.selected:
            self.selected.sprite.stop()
            self.selected.sprite.play()

            #self.selected.sprite.stop()
            #move = MoveTo( (x,y), round(time,1) )
            #self.selected.sprite.do( move + CallFunc(self.selected.sprite.pause))

            #orig = [29 - int(self.selected.sprite.y/20), int(self.selected.sprite.x/20)]
            #dest = [29 - y/20, x/20]
            #threading.Thread(target=move_object, args=[self.selected, self.astar, orig, dest]).start()

            end_pos   = Point2(x, y)
            start_pos = Point2(self.selected.sprite.x, self.selected.sprite.y)
            delta = end_pos - start_pos
            velocity = 4
            time = delta.magnitude()*1/(50.0*velocity)
            if time < 0.5: time = 0.5

            px = math.cos(-math.radians(self.selected.sprite.rotation))
            py = math.sin(-math.radians(self.selected.sprite.rotation))
            prev_pos = Point2(px, py)
            prev_pos.x += self.selected.sprite.x
            prev_pos.y += self.selected.sprite.y

            angle = vector2angle(prev_pos - start_pos, end_pos - start_pos)
            angle = math.degrees(angle)

            self.selected.sprite.stop()

            move = MoveTo( (x,y), round(time,1) )
            if angle != 0.0:
                rotate = Rotate(angle, 1)
                self.selected.sprite.do(rotate +
                                        move +
                                        CallFunc(self.selected.sprite.pause))
            else:
                self.selected.sprite.do(move +
                                        CallFunc(self.selected.sprite.pause))

        self.posx, self.posy = director.get_virtual_coordinates(x, y)
        self.character.set_pos(self.posx, self.posy)

        for garch in self.garchers:
            if garch.sprite.contains(x, y):
                garch.male.decopulate(garch.female,self)


    def monster_factory(self, dt):
        if self.number_of_monsters < 4:
            self.trayectories = [[randint(0, 800), randint(0, 600)] for x in range(5)]
            self.reptile = Monster('reptile_ANIM.png')
            self.reptile.setup_animation(13, 1)
            seq = Repeat(MoveTo(self.trayectories[0], 5) + MoveTo(self.trayectories[1], 5) + MoveTo(self.trayectories[2], 5) + MoveTo(self.trayectories[3], 5) + MoveTo(self.trayectories[4], 5))
            self.reptile.sprite.do(seq)
            self.add(self.reptile.sprite)
            self.number_of_monsters = self.number_of_monsters + 1
            self.monsters.append(self.reptile)

    def all_time(self, dt):
        for male in self.males:
            for female in self.females:
                if female.sprite.get_rect().intersects(male.sprite.get_rect()):
                    if not male.copulating and not female.copulating:
                        print "copulate"
                        garch = male.copulate(female, self)
                        self.garchers.append(garch)
                for monster in self.monsters:
                    monster_sprite = monster.sprite.get_rect()
                    if female.sprite.get_rect().intersects(monster_sprite):
                        female.sprite.stop()
                    if male.sprite.get_rect().intersects(monster_sprite):
                        male.sprite.stop()                   
                       

def vector2angle(v,w=None):
    """
       Get the angle between the X axis and the direction defined by v.
       The angle is in (-pi, pi] range
       If w is given then it is taken as the reference
       TODO: Check efficiency of this implementation
    """
    if w != None:
        ang2 = math.atan2(float(v[1]), float(v[0]))
        ang1 = math.atan2(float(w[1]), float(w[0]))
        dang = ang2 - ang1
        while dang > math.pi :
            dang = dang - 2.0*math.pi
        while dang < -math.pi :
            dang = dang + 2.0*math.pi

        return dang
    else:
        return (atan2(float(v[1]), float(v[0])))

def follow_path(path, callback):
    #print "follow path"
    try:
        y, x = path.pop()
        y = 29 - y
    except:
        return CallFunc(callback)
    
    where_to = ((x*20), (y*20))
    return MoveTo( where_to, 0.2 ) + follow_path(path, callback)
    
def move_object(_object, astar, orig, dest):
    print "Antes del path"
    path = astar.get_path_from_a_to_b(orig , dest)
    path.reverse()
    print "Despues del path"
    path = follow_path(path, _object.sprite.pause)

    if path:
        _object.sprite.do( path + follow_path(path, _object.sprite.pause) )
            
def get_newgame():
    '''returns the game scene'''
    main_scene = Scene()
    level = Level()
    main_scene.add(level, z=0)

    return main_scene
